import os
import math
import csv
import logging
from queue import Queue
from PyQt5.QtCore import pyqtSignal, QObject
from RcLogAnalyzer.scripts.database import DbHandler


class LogAnalyzer(QObject):
    analyze_result = {'lname': '', 'rname': '',
                      'lscore': 0, 'rscore': 0,
                      'l_pass_num': 0, 'r_pass_num': 0,
                      'l_intercept_num': 0, 'r_intercept_num': 0,
                      'l_dribble_num': 0, 'r_dribble_num': 0,
                      'l_long_pass': 0, 'r_long_pass': 0,
                      'l_normal_pass': 0, 'r_normal_pass': 0,
                      'l_short_pass': 0, 'r_short_pass': 0,
                      'l_through_pass': 0, 'r_through_pass': 0}
    __pass_features = []
    __pass_labels = []
    TOTAL_FEATURE_NUM = 60

    __output_through_pass_dataset = 0

    def __init__(self):
        self.logger = logging.getLogger('log_analyzer')
        self.logger.setLevel(logging.INFO)

        stream_handler = logging.StreamHandler()
        stream_handler.setLevel(logging.INFO)
        stream_handler.setFormatter(logging.Formatter('%(name)s - %(levelname)s - %(message)s'))

        self.logger.addHandler(stream_handler)

    def set_output_through_pass_dataset(self, is_output):
        self.__output_through_pass_dataset = is_output

    @staticmethod
    def __calc_player_distance(player_1, player_2):
        """计算球员距离

        Args:
            player_1: 球员1的数据字典
            player_2: 球员2的数据字典

        Returns:
            distance: 两个球员间的距离
        """
        x_distance = (player_1['posx'] - player_2['posx']) ** 2
        y_distance = (player_1['posy'] - player_2['posy']) ** 2
        distance = (x_distance + y_distance) ** 0.5
        return distance

    @staticmethod
    def __calc_passing_angle(player_passto, player_passer):
        """计算传球角度

        Args:
            player_passto: 被传球者的数据字典
            player_passer: 传球者的数据字典

        Returns:
            无
        """
        x_param = player_passto['posx'] - player_passer['posx']
        y_param = player_passto['posy'] - player_passer['posy']
        passing_angle = math.atan2(y_param, x_param)
        passing_angle = math.degrees(passing_angle)
        passing_angle = abs(passing_angle)
        return passing_angle

    def __is_through_pass(self, id_passer, id_receiver, current_cycle):
        # 获取传球者与接球者数据
        dict_player1 = self.__db_handler.dict_player(current_cycle, id_passer)
        dict_player2 = self.__db_handler.dict_player(current_cycle, id_receiver)

        # 接传球者x限制
        if dict_player2['posx'] < 20:
            return 0

        # 传球角度限制
        passing_angle = self.__calc_passing_angle(dict_player2, dict_player1)
        if passing_angle > 90:
            return 0

        # # 最终目的地限定
        # if abs(dict_player1['posy']) > 28:
        #     return 0

        # 传球距离限定
        passing_distance = self.__calc_player_distance(dict_player2, dict_player1)
        if passing_distance < 5:
            return 0

        # 计算突破人数
        through_opp_num = 0

        x1 = dict_player1['posx']
        y1 = dict_player1['posy']
        x2 = dict_player2['posx']
        y2 = dict_player2['posy']
        slope_pass_line = (y2 - y1) / (x2 - x1)
        vertical_slope = -1/slope_pass_line

        for i in range(12, 23):
            current_x = self.__db_handler.dict_player(current_cycle, i)['posx']
            current_y = self.__db_handler.dict_player(current_cycle, i)['posy']
            current_b = current_y - vertical_slope * current_x
            passer_b = y1 - vertical_slope * x1
            receiver_b = y2 - vertical_slope * x2
            if passer_b < receiver_b:
                if current_b < receiver_b and current_b > passer_b:
                    through_opp_num += 1
            if passer_b > receiver_b:
                if current_b > receiver_b and current_b < passer_b:
                    through_opp_num += 1

        if through_opp_num > 2:
            return 1
        else:
            return 0

    def through_pass_processing(self, id_passer, id_receiver, current_cycle):
        self.logger.info('through pass process start')
        """对传球信息的处理，获取所有特征数据，然后判断是否为突破传球保存标签信息

        Args:
            id_passer: 传球者编号
            id_receiver: 接传球者编号
            current_cycle: 传球瞬间周期

        Returns:
            无
        """
        # 获取特征数据 ==================================================
        # 获取传球者与接球者数据
        dict_player1 = self.__db_handler.dict_player(current_cycle, id_passer)
        dict_player2 = self.__db_handler.dict_player(current_cycle, id_receiver)

        self.__pass_features.append(dict_player1['posx'])
        self.__pass_features.append(dict_player1['posy'])
        self.__pass_features.append(dict_player1['velx'])
        self.__pass_features.append(dict_player1['vely'])
        self.__pass_features.append(dict_player1['bodydir'])
        # self.__pass_features.append(dict_player1['stamina'])
        self.__pass_features.append(dict_player2['posx'])
        self.__pass_features.append(dict_player2['posy'])
        self.__pass_features.append(dict_player2['velx'])
        self.__pass_features.append(dict_player2['vely'])
        self.__pass_features.append(dict_player2['bodydir'])

        # 获取地方2-10号球员数据
        for i in range(13, 23):
            dict_opponent = self.__db_handler.dict_player(current_cycle, i)
            self.__pass_features.append(dict_opponent['posx'])
            self.__pass_features.append(dict_opponent['posy'])
            self.__pass_features.append(dict_opponent['velx'])
            self.__pass_features.append(dict_opponent['vely'])
            self.__pass_features.append(dict_opponent['bodydir'])

        # # 判断是否为穿透传球 ==================================================
        # # 接传球者x限制
        # if dict_player2['posx'] < 20:
        #     self.__pass_labels.append(0)
        #     return
        #
        # # 传球角度限制
        # passing_angle = self.__calc_passing_angle(dict_player2, dict_player1)
        # if passing_angle > 90:
        #     self.__pass_labels.append(0)
        #     return
        #
        # # # 最终目的地限定
        # # if abs(dict_player1['posy']) > 28:
        # #     pass_labels.append(0)
        # #     return
        #
        # # 计算突破人数
        # through_opp_num = 0
        #
        # x1 = dict_player1['posx']
        # y1 = dict_player1['posy']
        # x2 = dict_player2['posx']
        # y2 = dict_player2['posy']
        # slope_pass_line = (y2 - y1) / (x2 - x1)
        # vertical_slope = -1/slope_pass_line
        #
        # passing_distance = self.__calc_player_distance(dict_player2, dict_player1)
        # if passing_distance < 5:
        #     self.__pass_labels.append(0)
        #     return
        #
        # for i in range(12, 23):
        #     current_x = self.__db_handler.dict_player(current_cycle, i)['posx']
        #     current_y = self.__db_handler.dict_player(current_cycle, i)['posy']
        #     current_b = current_y - vertical_slope * current_x
        #     passer_b = y1 - vertical_slope * x1
        #     receiver_b = y2 - vertical_slope * x2
        #     if passer_b < receiver_b:
        #         if current_b < receiver_b and current_b > passer_b:
        #             through_opp_num += 1
        #     if passer_b > receiver_b:
        #         if current_b > receiver_b and current_b < passer_b:
        #             through_opp_num += 1
        #
        # if through_opp_num > 2:
        #     self.__pass_labels.append(1)
        # else:
        #     self.__pass_labels.append(0)

        if self.__is_through_pass(id_passer, id_receiver, current_cycle) == 1:
            self.__pass_labels.append(1)
        else:
            self.__pass_labels.append(0)

    def clear(self):
        self.logger.info('clear start')
        self.analyze_result = {'lname': '', 'rname': '',
                               'lscore': 0, 'rscore': 0,
                               'l_pass_num': 0, 'r_pass_num': 0,
                               'l_intercept_num': 0, 'r_intercept_num': 0,
                               'l_dribble_num': 0, 'r_dribble_num': 0,
                               'l_long_pass': 0, 'r_long_pass': 0,
                               'l_normal_pass': 0, 'r_normal_pass': 0,
                               'l_short_pass': 0, 'r_short_pass': 0,
                               'l_through_pass': 0, 'r_through_pass': 0}
        self.__pass_features = []
        self.__pass_labels = []

    # 对rcg文件内容处理来获取模式信息
    def __rcg_processing(self, file_name):
        moden_queue = Queue()
        modes_queue = Queue()
        moden_queue.queue.clear();
        modes_queue.queue.clear();

        with open(file_name, 'r') as f_read:
            lines = f_read.readlines()
        for line in lines:
            if line[1:9] == 'playmode':
                playmode_info = line.split(' ')
                modecycle = playmode_info[1]
                playmode = playmode_info[2][:-2]
                if playmode == 'play_on':
                    moden_queue.put(modecycle)
                else:
                    modes_queue.put(modecycle)

        return moden_queue, modes_queue

    def __save_dataset(self):
        self.logger.info('save dataset start')
        dataset_write = open('./output/dataset/through_pass_dataset.csv', 'a')

        csv_writer = csv.writer(dataset_write)

        for i in range(int(len(self.__pass_features)/self.TOTAL_FEATURE_NUM)):
            current_data = self.__pass_features[i*self.TOTAL_FEATURE_NUM:(i+1)*self.TOTAL_FEATURE_NUM]
            current_data.append(self.__pass_labels[i])
            csv_writer.writerow(current_data)

        dataset_write.close()

        self.logger.info('save dataset finish')

        # for i in range(int(len(self.__pass_features)/self.TOTAL_FEATURE_NUM)):
        #     for j in range(self.TOTAL_FEATURE_NUM):
        #         features_write.write(str(self.__pass_features[i*self.TOTAL_FEATURE_NUM+j]))
        #         if j != self.TOTAL_FEATURE_NUM-1:
        #             features_write.write(',')
        #         else:
        #             features_write.write('\n')
        #
        # for i in range(len(self.__pass_labels)):
        #     labels_write.write(str(self.__pass_labels[i]))
        #     labels_write.write(',')


    # 处理rcl文件
    def analyze(self, rcl_name, data_dir):
        self.logger.info('log analyze start')
        # 初始化
        self.__db_handler = DbHandler()
        data_name = os.path.split(rcl_name)[1]
        data_name = data_name[:-3] + 'db'
        data_name = os.path.join(data_dir, data_name)

        self.__db_handler.open(data_name)

        # 记录当前是否为特殊模式，是为1，不是为0
        is_special_mode = 0

        prekick_object = 0
        prekick_cycle = 0

        # 去除路径的纯文件名
        pure_file_name = os.path.split(rcl_name)[1]

        # 获取球队名
        file_info = pure_file_name.split('-')
        self.analyze_result['lname'] = file_info[1].split('_')[0]
        self.analyze_result['rname'] = file_info[3].split('_')[0]
        self.analyze_result['lscore'] += int(file_info[1].split('_')[1])
        self.analyze_result['rscore'] += int(
            file_info[3].split('_')[1].split('.')[0])

        # 读取rcg文件来获取模式信息
        moden_queue, modes_queue = self.__rcg_processing(
            rcl_name[:-1] + 'g')

        # 读取rcl文件处理传球信息
        with open(rcl_name, 'r') as f_read:
            lines = f_read.readlines()

        for line in lines:
            # 获取周期
            index = line.find(',')
            cycle = line[0:index]

            # 去除周期为0和6000的行
            if cycle == '0' or cycle == '6000' or int(cycle) > 6000:
                continue

            # 判断模式
            if not moden_queue.empty():
                if moden_queue.queue[0] == cycle:
                    is_special_mode = 0
                    moden_queue.get()
            if not modes_queue.empty():
                if modes_queue.queue[0] == cycle:
                    is_special_mode = 1
                    modes_queue.get()

            # 如果当前不是play_on模式，不处理
            if is_special_mode:
                prekick_object = 0
                continue

            # 获取球员id
            index = line.find('Recv ')
            if index == -1:
                continue
            index_2 = line.find(':')
            player = line[index + 5:index_2]
            if player.split('_')[1] == 'Coach':
                continue
            if player.split('_')[0] == self.analyze_result['lname']:
                player_id = player.split('_')[1]
            else:
                player_id = str(int(player.split('_')[1]) + 11)

            # 获取动作
            index = line.find('(')
            index_2 = line.find(')')
            action = line[index + 1:index_2].split(' ')[0]

            # 去除不是kick的动作
            if action != 'kick':
                continue

            # 如果不存在上一个踢球的球员，这周期不判断
            if prekick_object == 0:
                prekick_object = player_id
                prekick_cycle = cycle
                continue
            if prekick_cycle == 0:
                prekick_object = player_id
                prekick_cycle = cycle
                continue

            # 如果上一个踢球的是门将，不考虑
            if prekick_object == 1:
                prekick_object = player_id
                prekick_cycle = cycle
                continue

            # 如果当前踢球球员与上一个相同，带球+1
            if player_id == prekick_object:
                if int(player_id) < 12:
                    # TODO:左方带球+1
                    self.analyze_result['l_dribble_num'] += 1
                else:
                    # TODO:右方带球+1
                    self.analyze_result['r_dribble_num'] += 1
            # 如果当前踢球球员与上一个都是左边的，传球+1
            elif int(player_id) < 12 and int(prekick_object) < 12:
                # TODO:左方传球+1
                self.analyze_result['l_pass_num'] += 1

                if self.__is_through_pass(prekick_object, player_id, prekick_cycle) == 1:
                    self.analyze_result['l_through_pass'] += 1

                if self.__output_through_pass_dataset == 1:
                    self.through_pass_processing(prekick_object, player_id, prekick_cycle)

            # 如果当前踢球球员与上一个都是右边的，传球+1
            elif int(player_id) > 11 and int(prekick_object) > 11:
                # TODO:右方传球+1
                self.analyze_result['r_pass_num'] += 1

            # 如果当前踢球球员是左边的，上一个是右边的，截球+1
            elif int(player_id) < 12 and int(prekick_object) > 11:
                # TODO:左方截球
                self.analyze_result['l_intercept_num'] += 1
            # 如果当前踢球球员是右边的，上一个是左边的，截球+1
            elif int(player_id) > 11 and int(prekick_object) < 12:
                # TODO:右方截球
                self.analyze_result['r_intercept_num'] += 1

            prekick_object = player_id
            prekick_cycle = cycle

        self.__db_handler.close()
        if self.__output_through_pass_dataset == 1:
            self.__save_dataset()
